// 导入路由实例
import router from './router'
// 导入vuex存储实例
import store from './store'
// 导入 Element UI 的消息提示组件
import { Message } from 'element-ui'
// 导入 NProgress（用于显示页面加载进度条）
import NProgress from 'nprogress'
// 导入 NProgress 的样式文件
import 'nprogress/nprogress.css'
// 导入获取 token 的工具函数
import { getToken } from '@/utils/auth'
// 导入路径匹配的工具函数
import { isPathMatch } from '@/utils/validate'
// 导入重新登录的工具函数
import { isRelogin } from '@/utils/request'

// 配置 NProgress 不显示加载 spinner
NProgress.configure({ showSpinner: false })

// 定义免登录白名单（不需要登录即可访问的路由）
const whiteList = ['/login', '/register']

// 判断当前路径是否在白名单中
const isWhiteList = (path) => {
    return whiteList.some(pattern => isPathMatch(pattern, path))
}

// 全局前置路由守卫
router.beforeEach((to, from, next) => {
    // 开始加载进度条
    NProgress.start()

    // 判断用户是否已登录（是否有 token）
    if (getToken()) {
        // 如果已登录，设置页面标题（如果路由元信息中有 title）
        to.meta.title && store.dispatch('settings/setTitle', to.meta.title)

        // 如果用户已登录且尝试访问登录页，则重定向到首页
        if (to.path === '/login') {
            next({ path: '/' })
            NProgress.done()
        }
        // 如果访问的是白名单中的路由，直接放行
        else if (isWhiteList(to.path)) {
            next()
        }
        // 其他情况
        else {
            // 如果用户角色信息未拉取，则拉取用户信息
            if (store.getters.roles.length === 0) {
                // 设置重新登录标志为 true
                isRelogin.show = true

                // 拉取用户信息
                store.dispatch('GetInfo').then(() => {
                    // 拉取成功后，关闭重新登录标志
                    isRelogin.show = false

                    // 根据用户角色生成动态路由
                    store.dispatch('GenerateRoutes').then(accessRoutes => {
                        // 动态添加路由到路由器
                        router.addRoutes(accessRoutes)

                        // 使用 hack 方法确保路由添加完成后再跳转
                        next({ ...to, replace: true })
                    })
                }).catch(err => {
                    // 如果拉取用户信息失败，执行登出操作
                    store.dispatch('LogOut').then(() => {
                        // 显示错误消息
                        Message.error(err)
                        // 重定向到首页
                        next({ path: '/' })
                    })
                })
            } else {
                // 如果用户角色信息已拉取，直接放行
                next()
            }
        }
    }
    // 如果用户未登录
    else {
        // 如果访问的是白名单中的路由，直接放行
        if (isWhiteList(to.path)) {
            next()
        }
        // 否则重定向到登录页，并携带当前路径作为重定向参数
        else {
            next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
            NProgress.done()
        }
    }
})

// 全局后置路由守卫
router.afterEach(() => {
    // 结束加载进度条
    NProgress.done()
})
